#include "include.h"
int Recv_size;
#define Send_size 1024

// 读取文件,获取ＩＰ和端口号
void getIPPort(uint32_t *ip, int *port);

void SendSTM(int si);
void RecvSTM(int si);
// 发送结构体

struct data Data[8];

struct message RDATA;
struct message ATA;
struct shm_param shm;
// 接收数据
// struct data Recv_buf;
char Recv_buf[400] = "";
char Send_buf[64] = "";
// 锁定数组下标
int iSTM = 0;
// 锁定对方ＩＰ
int ipSTM = 0;
#define N 10
struct pollfd fds[N];
int last = -1; // 初始表长度
void *handler(void *agr)
{
    while (1)
    {
        msg_queue_recv("stm32", &RDATA, sizeof(RDATA), 0, 0);
        printf("发送---\n");
        if (RDATA.key == 305) // 灯
        {
            if (RDATA.val.b_val == 1)
            {
                for (int j = 2; j <= last; j++)
                {
                    int s = send(fds[j].fd, "lo", 2, 0);
                }
            }
            else
            {
                for (int j = 2; j <= last; j++)
                {
                    int s = send(fds[j].fd, "lf", 2, 0);
                }
            }
        }
        else if (RDATA.key == 306) // buzz
        {
            if (RDATA.val.b_val == 1)
            {
                for (int j = 2; j <= last; j++)
                {
                    int s = send(fds[j].fd, "bo", 2, 0);
                }
            }
            else
            {
                for (int j = 2; j <= last; j++)
                {
                    int s = send(fds[j].fd, "bf", 2, 0);
                }
            }
        }
        else if (RDATA.key == 307) // fan
        {
            if (RDATA.val.b_val == 1)
            {
                for (int j = 2; j <= last; j++)
                {
                    int s = send(fds[j].fd, "fo", 2, 0);
                }
            }
            else
            {
                for (int j = 2; j <= last; j++)
                {
                    int s = send(fds[j].fd, "ff", 2, 0); // 关
                }
            }
        }
        else if (RDATA.key == 308) // motor
        {
            printf("308308\n");
            if (RDATA.val.b_val == 1)
            {
                for (int j = 2; j <= last; j++)
                {
                    int s = send(fds[j].fd, "mo", 2, 0); // 关
                }
            }
            else
            {
                for (int j = 2; j <= last; j++)
                {
                    int s = send(fds[j].fd, "mf", 2, 0); // 关
                }
            }
        }
    }
}

int main(int argc, char const *argv[])
{
    struct device *device = (struct device *)malloc(sizeof(struct device));
    // 绑定设备
    deserialization(device, Data);
    // for (int i = 0; i < 9; i++)
    // {
    //     /* code */
    //       printf("Data[%d] key:%ld name:%s type:%d\n",i, Data[i].key,Data[i].name,Data[i].type );
    // }
    // 开辟共享内存
    shm_init(&shm, "haha", 1024);
    // struct data *p = (struct data *)shm_getaddr(&shm);
    int *pt = shm_getaddr(&shm);
    printf("设备数量：%d\n", *pt);
    printf("共享内存首地址:%p\n", pt);
    // 移动共享内存到ｓｔｍ数据域
    struct data *p = (struct data *)(pt + 2);
    Recv_size = sizeof(Recv_buf);
    // １套接字
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    // ２绑定
    struct sockaddr_in ad;
    // 端口重用
    int v = 1;
    socklen_t lenv = sizeof(v);
    setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &v, lenv);

    // 从终端输入获取IP和端口
    int32_t ip;
    int port;
    getIPPort(&ip, &port);
    ad.sin_addr.s_addr = ip;
    ad.sin_port = port;
    ad.sin_family = AF_INET;
    socklen_t len = sizeof(ad);
    if (bind(sfd, (struct sockaddr *)&ad, len) < 0)
    {
        perror("file");
        return -1;
    }
    listen(sfd, 8);

    char buf[64] = "";
    // 创建表

    fds[++last].fd = 0; /*  */
    fds[last].events = POLLIN;
    fds[++last].fd = sfd;
    fds[last].events = POLLIN;

    while (1)
    {
        poll(fds, last + 1, -1);

        pthread_t tid;
        pthread_create(&tid, NULL, handler, NULL);
        // max = tid;
        pthread_detach(tid);
        // 结构体，大小，无定时．无操作时一直阻塞

        for (int i = 0; i <= last; i++)
        {
            // 如果文件描述符i有输入
            if (fds[i].revents == POLLIN)
            {
                // 判断输入来源
                // 如果是链接套接字
                if (fds[i].fd == sfd)
                {
                    // 创建通信套接字
                    printf("连接成功");
                    int afd = accept(sfd, (struct sockaddr *)&ad, &len);
                    fds[++last].fd = afd;
                    fds[last].events = POLLIN;
                    fds[last].revents = 0;
                }
                // 如果是标准输入
                else if (fds[i].fd == 0)
                {
                    // memset(buf, 0, 64);
                    // gets(buf);
                    // ATA.key = 308;
                    // if (strcmp(buf, "mo") == 0)
                    // {
                    //     ATA.val.b_val = 1;
                    //     msg_queue_send("stm32", &ATA, sizeof(ATA), 0);
                    // }
                    // else if (strcmp(buf, "mf") == 0)
                    // {

                    //     ATA.val.b_val = 0;
                    //     msg_queue_send("stm32", &ATA, sizeof(ATA), 0);
                    // }

                    // msg_queue_recv("stm32", &RDATA, sizeof(RDATA), 0, 0);

                    // 注意，我们要将信息发送给所有客户端，所有需要重新遍历，注意开始位置
                    // for (int j = 2; j <= last; j++)
                    // {
                    //     int s = send(fds[j].fd, buf, 64, 0);
                    // }
                }
                // 接收,如果不是标准输入，也不是连接套接字输入，那就是有端口发来了消息，属于信息套接字有输入
                else
                {
                    int ret = recv(fds[i].fd, Recv_buf, 400, 0);
                    if (ret < 0)
                    {
                        perror("ret err");
                    }
                    else if (ret > 0)
                    {

                        int len = strlen(Recv_buf);
                        printf("heand%c\n", Recv_buf[0]);
                        printf("len = %s\n", &Recv_buf[len - 2]);
                        if (strcmp(&Recv_buf[len - 2], "]}") == 0 && Recv_buf[0] == '{') // 保证接到的格式正确
                        {

                            cJSON *root = cJSON_Parse(Recv_buf);
                            printf("111%s\n", Recv_buf);

                            cJSON *stm32Data = cJSON_GetObjectItem(root, "data");
                            // printf("222%s\n", Recv_buf);
                            for (int i = 0; i < 9; i++)
                            {
                                cJSON *item = cJSON_GetArrayItem(stm32Data, i);
                                cJSON *key = cJSON_GetObjectItem(item, "key");
                                printf("key:%d\n", key->valueint);
                                cJSON *val = cJSON_GetObjectItem(item, "val");
                                printf("val:%.1f\n", val->valuedouble);
                                // 查找对应设备
                                struct data *temp = p;
                                for (int i = 0; i < 9; i++)
                                {
                                    if (Data[i].key == key->valueint)
                                    {
                                        iSTM = i;
                                        if (Data[i].type == 3)
                                        {
                                            Data[i].val.f_val = val->valuedouble;
                                            temp->val.f_val = val->valuedouble;

                                            // (p + iSTM)->val.f_val = val->valuedouble;
                                            // // printf("p = %f\n", (p + iSTM)->val.f_val);
                                            // printf("名字%s\n", temp->name);
                                            // printf("键值%ld\n", temp->key);
                                            // printf("真实的值%.2f\n", temp->val.f_val);
                                            // printf("指针地址:%p\n", temp);
                                        }
                                        else if (Data[i].type == 2)
                                        {
                                            Data[i].val.i_val = val->valueint;
                                            // (p + iSTM)->val.i_val = val->valueint;
                                            // printf("p = %d\n", (p + iSTM)->val.i_val);
                                            temp->val.i_val = val->valueint;
                                        }
                                        else
                                        {
                                            Data[i].val.b_val = val->valueint;
                                            // (p + iSTM)->val.b_val = val->valueint;
                                            // printf("p = %d\n", (p + iSTM)->val.b_val);
                                            temp->val.b_val = val->valueint;
                                        }
                                        // 指针归位

                                        // break;
                                    }
                                    temp++;
                                }
                            }
                            cJSON_Delete(root);
                        }
                        // 释放节点的内存，防止内存泄露

                        memset(Recv_buf, 0, 400);
                    }
                    // =0 有端口退出
                    else
                    {
                        printf("%d:quit\n", fds[i].fd);
                        close(fds[i].fd);
                        fds[i--] = fds[last--];
                    }
                }
            }
        }
    }

    return 0;
}

// 读取文件,获取ＩＰ和端口号
void getIPPort(uint32_t *ip, int *port)
{
    int fd = open("./info.txt", O_RDONLY);
    if (fd < 0)
    {
        perror("open file err.");
        return;
    }
    // 获取ＩＰ
    char txt[32] = "";
    int i = -1;
    // 文件指针偏移
    lseek(fd, 3, SEEK_SET);
    while (strcmp(txt, "\n"))
    {
        read(fd, txt, 1);
        i++;
    }
    lseek(fd, 3, SEEK_SET);
    read(fd, txt, i);
    *ip = inet_addr(txt);
    printf("ip: %s\n", txt);

    // 获取端口
    lseek(fd, 6, SEEK_CUR);
    memset(txt, 0, 32);
    i = 0;
    while (1)
    {
        if (read(fd, txt, 1) == 0)
            break;
        i++;
    }
    lseek(fd, -i, SEEK_END);
    read(fd, txt, i);
    *port = (htons(atoi(txt)));
    printf("port:%s\n", txt);

    close(fd);
}
void SendSTM(int si)
{
    // // 发送
    // send(si, Send_buf, 64, 0);
    send(si, "Send_buf", 64, 0);
}
void RecvSTM(int si)
{
    printf("%s\n", Recv_buf);
}